package com.codi.bus.core.service.impl;

import com.codi.base.exception.BaseAppException;
import com.codi.base.exception.ExceptionHandler;
import com.codi.base.util.EqualsUtil;
import com.codi.base.util.MoneyUtils;
import com.codi.bus.constant.GlobalConstant;
import com.codi.bus.core.dao.FundCombinationDao;
import com.codi.bus.core.dao.FundCombinationMappingDao;
import com.codi.bus.core.dao.FundInfoDao;
import com.codi.bus.core.domain.*;
import com.codi.bus.core.resultModel.BaseResult;
import com.codi.bus.core.resultModel.FundCombinationDetailsResult;
import com.codi.bus.core.resultModel.FundCombinationResult;
import com.codi.bus.core.resultModel.FundInfoCombinationResult;
import com.codi.bus.core.service.*;
import com.codi.bus.core.service.model.PortfolioQryModel;
import com.codi.bus.core.service.util.FundUtil;
import com.codi.bus.core.service.util.HundsunUtils;
import com.codi.bus.core.service.util.ModelPopulateUtils;
import com.codi.bus.core.vo.FundCombinationVo;
import com.codi.bus.core.vo.FundVo;
import com.codi.fundData.domain.FundDetail;
import com.codi.fundData.domain.FundNetValuePerformance;
import com.codi.message.constant.ErrorConst;
import com.codi.trade.dto.PortfolioQryDto;
import com.codi.trade.service.portfolio.HsPortfolioQryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
@Service("fundCombinationService")
@Transactional(readOnly = true)
public class FundCombinationServiceImpl implements FundCombinationService {

    @Resource
    private FundCombinationDao fundCombinationDao;

    @Resource
    private FundCombinationMappingDao fundCombinationMappingDao;

    @Resource
    private FundInfoDao fundInfoDao;

    @Autowired
    private HsPortfolioQryService hsPortfolioQryService;

    @Autowired
    private FundDetailService fundDetailService;

    @Autowired
    private WorkingDateService workingDateService;

    @Autowired
    private QueryService queryService;

    @Autowired
    private FundCombinationMappingService fundCombinationMappingService;

    @Autowired
    private FundCombinationHistoryService fundCombinationHistoryService;

    @Override
    public List<FundCombinationResult> queryThreeCombinations() {
        List<FundCombinationResult> results = queryPortfolios();

        if (results.size() >= 3) {
            return results.subList(0, 3);
        }

        return results;
    }

    public FundCombination queryOne(String combinationCode) {
        return fundCombinationDao.queryByCombinationCode(combinationCode);
    }

    @Override
    public FundCombination queryByPrimaryKey(Long combinationId) {
        return fundCombinationDao.queryByPrimaryKey(combinationId);
    }

    @Override
    public FundCombinationDetailsResult queryByCombinationCode(String combinationCode) {
        FundCombination                 combination   = fundCombinationDao.queryByCombinationCode(combinationCode);
        List<FundCombinationMapping>    mappings      = fundCombinationMappingDao.query(combinationCode);
        List<FundInfoCombinationResult> results       = new ArrayList<>();
        FundCombinationDetailsResult    detailsResult = new FundCombinationDetailsResult();

        PortfolioQryDto dto = PortfolioQryDto.builder().request_num(GlobalConstant.MAX_REQUEST_NUM).sort_direction("1").qry_beginrownum("1").build();

        Map<String, Object> map = hsPortfolioQryService.query(dto);

        BaseResult                result = new BaseResult();
        List<Map<String, Object>> list   = new ArrayList<>();
        HundsunUtils.ConvertToList(map, list, result);

        if (!result.getSuccess()) {
            log.error("获取基金组合失败");
            ExceptionHandler.publish(ErrorConst.COMMON_SYSTEM_ERROR);
        }

        List<PortfolioQryModel> portfolioQryModels = ModelPopulateUtils.populatePortfolioQry(list);



//        log.debug("**************************test************************");
//
//        log.info(JSONObject.toJSONString(portfolioQryModels));
//
//        log.debug("**************************test************************");

        Iterator<PortfolioQryModel> modelss = portfolioQryModels.iterator();

        while (modelss.hasNext()) {
            PortfolioQryModel model = modelss.next();

//            if ("0".equals(model.getCombState().trim())) {
//                modelss.remove();
//            }

            if (model.getEndDate().before(new Date())) {
                modelss.remove();
            }
        }

        if (combination != null) {
            for (PortfolioQryModel model : portfolioQryModels) {
                if (combinationCode.equals(model.getPortfolioCode())) {
                    combination.setCombinationName(model.getProtocolName());

                    break;
                }
            }

            BeanUtils.copyProperties(combination, detailsResult);

            for (PortfolioQryModel model : portfolioQryModels) {
                if (combinationCode.equals(model.getPortfolioCode())) {
                    FundInfo                  fundInfo          = fundInfoDao.getFundInfoByFundCode(model.getFundCode().trim());

                    if (fundInfo == null) {
                        continue;
                    }

                    FundInfoCombinationResult combinationResult = new FundInfoCombinationResult();
                    BeanUtils.copyProperties(fundInfo, combinationResult);
                    FundCombinationMapping mapping = fundCombinationMappingService.queryByCombinationCodeAndFundCode(model.getPortfolioCode().trim(), fundInfo.getFundCode().trim());

                    if (mapping == null) {
                        continue;
                    }

                    combinationResult.setFundPercent(mapping.getFundPercent());
                    combinationResult.setFundShareType(model.getShareType());

                    results.add(combinationResult);
                }
            }

            detailsResult.setFundInfoCombinationResults(results);
        }

        //设置交易日 日期
        Date lastWorkingDate = workingDateService.getLastWorkingDay(combination.getLastUpdatedDate()).getLastWorkingDay();
        detailsResult.setTradeDate(lastWorkingDate);

        return detailsResult;
    }

    @Override
    public List<FundCombinationResult> queryPortfolios() {
        PortfolioQryDto dto = PortfolioQryDto.builder().request_num(GlobalConstant.MAX_REQUEST_NUM).sort_direction("1").qry_beginrownum("1").build();
        Map<String, Object> map = hsPortfolioQryService.query(dto);

        BaseResult                result = new BaseResult();
        List<Map<String, Object>> list   = new ArrayList<>();
        HundsunUtils.ConvertToList(map, list, result);

        if (!result.getSuccess()) {
            log.error("获取基金组合失败");
            ExceptionHandler.publish(ErrorConst.COMMON_SYSTEM_ERROR);
        }

        List<PortfolioQryModel> portfolioQryModels = ModelPopulateUtils.populatePortfolioQry(list);

        Set<String> portfolios = new HashSet<>();
        for (PortfolioQryModel model : portfolioQryModels) {
//            if ("1".equals(model.getCombState())) {
//                portfolios.add(model.getPortfolioCode());
//            }

            if (model.getEndDate().after(new Date())) {
                portfolios.add(model.getPortfolioCode());
            }
        }

        List<String> portfolioCodes = new ArrayList<>(portfolios);

        List<FundCombination>       combinations = null;
        List<FundCombinationResult> results      = new ArrayList<>();

        if (portfolioCodes.size() != 0) {
            combinations = fundCombinationDao.queryPortfolio(portfolioCodes);

            for (FundCombination fundCombination : combinations) {
                for (PortfolioQryModel model : portfolioQryModels) {
                    if (fundCombination.getCombinationCode().equals(model.getPortfolioCode())) {
                        fundCombination.setCombinationName(model.getProtocolName());
                        fundCombination.setInnerCombCode(model.getInnerCombcode());
                    }
                }
            }

            for (FundCombination combination : combinations) {
                FundCombinationResult fundCombinationResult = new FundCombinationResult();
                BeanUtils.copyProperties(combination, fundCombinationResult);
                results.add(fundCombinationResult);
            }
        }

        return results;
    }



    @Override
    public List<String> queryFundCodes(String combinationCode) {
        List<String> fundCodes = new ArrayList<>();
        PortfolioQryDto dto = PortfolioQryDto.builder().request_num(GlobalConstant.MAX_REQUEST_NUM).sort_direction("1").qry_beginrownum("1").build();
        Map<String, Object> map = hsPortfolioQryService.query(dto);

        BaseResult                result = new BaseResult();
        List<Map<String, Object>> list   = new ArrayList<>();
        HundsunUtils.ConvertToList(map, list, result);

        if (!result.getSuccess()) {
            log.error("获取基金组合失败");
            ExceptionHandler.publish(ErrorConst.COMMON_SYSTEM_ERROR);
        }

        List<PortfolioQryModel> portfolioQryModels = ModelPopulateUtils.populatePortfolioQry(list);

        for (PortfolioQryModel model : portfolioQryModels) {
            if (combinationCode.equals(model.getPortfolioCode())) {
                fundCodes.add(model.getFundCode());
            }
        }

        return fundCodes;
    }

    @Override
    public List<FundCombination> queryAll() {
        return fundCombinationDao.queryAll();
    }

    @Transactional(readOnly = false)
    public void updateFundCombination() throws BaseAppException {
        List<FundCombinationVo> fundCombinationVos = getDailyGrowthRates();

        for (FundCombinationVo vo : fundCombinationVos) {
            FundCombination combination = fundCombinationDao.queryByCombinationCode(vo.getCombinationCode());

            if (combination == null) {
                continue;
            }

            combination.setDailyCent(vo.getDailyGrowthRate());
            combination.setAnnualizedIncome(vo.getAnnualizedIncome());
            combination.setAccumCurrencyIncome(vo.getAccumCurrencyIncome());
            combination.setAccumulatedIncome(vo.getAccumulatedIncome());
            combination.setRunDay(vo.getRunDay());

            fundCombinationDao.updatePortfolio(combination);

            FundCombinationHistory history = new FundCombinationHistory();
            BeanUtils.copyProperties(combination, history);
            history.setCalDate(new Date());
            history.setTradeDate(vo.getTradeDate());

            fundCombinationHistoryService.add(history);
        }
    }


    /**
     * 组合上线特殊需求
     * @param
     * @return
     */
    @Transactional(readOnly = false)
    public void updateFundCombination2(Date currentDate) throws BaseAppException {
        List<FundCombinationVo> fundCombinationVos = getDailyGrowthRates2(currentDate);

        for (FundCombinationVo vo : fundCombinationVos) {
            FundCombination combination = fundCombinationDao.queryByCombinationCode(vo.getCombinationCode());

            if (combination == null) {
                continue;
            }

            combination.setDailyCent(vo.getDailyGrowthRate());
            combination.setAnnualizedIncome(vo.getAnnualizedIncome());
            combination.setAccumCurrencyIncome(vo.getAccumCurrencyIncome());
            combination.setAccumulatedIncome(vo.getAccumulatedIncome());
            combination.setRunDay(vo.getRunDay());

            fundCombinationDao.updatePortfolio(combination);

            FundCombinationHistory history = new FundCombinationHistory();
            BeanUtils.copyProperties(combination, history);
            history.setCalDate(new Date());
            history.setTradeDate(vo.getTradeDate());

            fundCombinationHistoryService.add(history);
        }
    }

    @Override
    @Transactional(readOnly = false)
    public int deleteByCombinationCode(String combinationCode) {
        return fundCombinationDao.deleteByCombinationCode(combinationCode.trim());
    }


    @Transactional(readOnly = false)
    public List<FundCombinationVo> getDailyGrowthRates() throws BaseAppException{

        Map<String, Object> map = hsPortfolioQryService.query(new PortfolioQryDto());

        BaseResult                result = new BaseResult();
        List<Map<String, Object>> list   = new ArrayList<>();
        HundsunUtils.ConvertToList(map, list, result);

        if (!result.getSuccess()) {
            log.error("获取基金组合失败");
            ExceptionHandler.publish(ErrorConst.COMMON_SYSTEM_ERROR);
        }

        List<PortfolioQryModel> portfolioQryModels = ModelPopulateUtils.populatePortfolioQry(list);

        /**
         * test code
         */
        Iterator<PortfolioQryModel> modelss = portfolioQryModels.iterator();
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

        while (modelss.hasNext()) {
            PortfolioQryModel a = modelss.next();

            try {
                if ("3001".equals(a.getPortfolioCode().trim())) {
                    a.setBeginDate(dateFormat.parse("2017-8-18"));
                }

                if ("3002".equals(a.getPortfolioCode().trim())) {
                    a.setBeginDate(dateFormat.parse("2017-9-15"));
                }

                if ("3003".equals(a.getPortfolioCode().trim())) {
                    a.setBeginDate(dateFormat.parse("2017-8-7"));
                }
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }



        Set<String> portfolios = new HashSet<>();

        for (PortfolioQryModel model : portfolioQryModels) {
            if ("1".equals(model.getCombState())) {
                portfolios.add(model.getPortfolioCode());
            }
        }

        List<String> portfolioCodes = new ArrayList<>(portfolios);
        List<FundCombinationVo> fundCombinationVos = new ArrayList<>();

        for (String code : portfolioCodes) {
            FundCombinationVo vo = new FundCombinationVo();
            vo.setCombinationCode(code);

            BigDecimal sumDailyGrowthRate = new BigDecimal(0);

            for (PortfolioQryModel model : portfolioQryModels) {
                if (code.equals(model.getPortfolioCode())) {
                    vo.setCombinationName(model.getProtocolName());

                    try {
                        BigDecimal fundDailyGrowthRate = fundDetailService.getFundDailyGrowthRate(model.getFundCode());

                        if (fundDailyGrowthRate == null) {
                            fundDailyGrowthRate = new BigDecimal(0);
                        }

                        BigDecimal finalDailyGrowthRate = fundDailyGrowthRate.multiply(model.getInvestRate());
                        sumDailyGrowthRate = sumDailyGrowthRate.add(finalDailyGrowthRate);
                    } catch (BaseAppException e) {
                        log.error(e.getMessage(), e);
                    }
                }
            }

            vo.setDailyGrowthRate(MoneyUtils.parseRate(sumDailyGrowthRate));

            fundCombinationVos.add(vo);
        }

        /**
         * 计算组合累计收益
         */
        for (FundCombinationVo vo : fundCombinationVos) {
            BigDecimal accumulatedIncome = new BigDecimal(0);
            FundCombination combination = queryOne(vo.getCombinationCode());

            if (combination == null) {
                continue;
            }

            //货币基金累计收益
            float accumCurrencyIncome = combination.getAccumCurrencyIncome();
            BigDecimal accCurrencyIncome = new BigDecimal(accumCurrencyIncome);
            accumulatedIncome = accumulatedIncome.add(accCurrencyIncome);

            BigDecimal baseCalculate = new BigDecimal(combination.getBaseCalculate());
            Date beginDate = null;

            //test---------------
//            String input = "2017-11-1";
//            DateFormat df = new SimpleDateFormat("yyyy-MM-dd");

            List<FundVo> fundVos = new ArrayList<>();

            for (PortfolioQryModel model : portfolioQryModels) {

                beginDate = model.getBeginDate();
//                try {
//                    beginDate = df.parse(input);
//                } catch (ParseException e) {
//                    e.printStackTrace();
//                }
                if (beginDate == null) {
                    continue;
                }

//                vo.setBeginDate(beginDate);

                Date tradeDay = workingDateService.getLastWorkingDay(beginDate).getLastWorkingDay();



                if (tradeDay == null) {
                    continue;
                }

                Date todayTradeDay = workingDateService.getLastWorkingDay(new Date()).getLastWorkingDay();

                if (vo.getCombinationCode().equals(model.getPortfolioCode())) {

                    //判断历史表是否有重复组合交易日数据，若有，则不再计算

                    List<FundCombinationHistory> histories = fundCombinationHistoryService.queryByTradeDay(vo.getCombinationCode(), todayTradeDay);

                    if (histories != null && histories.size() != 0) {
                        continue;
                    }

                    vo.setBeginDate(beginDate);
                    vo.setTradeDate(todayTradeDay);

                    //轮询基金
                    FundDetail fundDetail = fundDetailService.getFundDetail(model.getFundCode().trim());

                    if (fundDetail == null) {
                        continue;
                    }

                    boolean isCurrency = FundUtil.isCurrency(fundDetail.getFundTypeCode());

                    if (isCurrency) {
                        //货基
                        BigDecimal dailyProfit = fundDetailService.getCurrencyDailyProfit(model.getFundCode());
                        BigDecimal todayIncome = baseCalculate.multiply(model.getInvestRate()).multiply(dailyProfit).divide(new BigDecimal(10000));
                        accumulatedIncome = accumulatedIncome.add(todayIncome);
                        accCurrencyIncome = accCurrencyIncome.add(todayIncome);

                        //计算该货基资产
                        FundCombinationMapping mapping = fundCombinationMappingService.queryByCombinationCodeAndFundCode(vo.getCombinationCode(), model.getFundCode().trim());

                        if (mapping == null) {
                            continue;
                        }

                        Float fundCurrencyAccumIncome = mapping.getFundCurrencyAccumIncome();

                        BigDecimal fundCurrencyAccumIncomeB = null;

                        if (fundCurrencyAccumIncome == null) {
                            fundCurrencyAccumIncomeB = new BigDecimal(0);
                        } else {
                            fundCurrencyAccumIncomeB = new BigDecimal(fundCurrencyAccumIncome);
                        }
                        //货币资产
                        BigDecimal fundAssets = fundCurrencyAccumIncomeB.add(todayIncome).add(baseCalculate.multiply(model.getInvestRate()));
                        mapping.setFundCurrencyAccumIncome(fundCurrencyAccumIncomeB.add(todayIncome).floatValue());

                        //更新mapping中货基累计值
                        fundCombinationMappingService.update(mapping);

                        FundVo fundVo = new FundVo();
                        fundVo.setFundCode(model.getFundCode().trim());
                        fundVo.setFundAssets(fundAssets);
//                        fundVo.setBeginDate(beginDate);
                        fundVos.add(fundVo);
                    } else {
                        //非货基

                        //当前净值
                        FundNetValuePerformance performance = fundDetailService.getFundNetValuePerformance(model.getFundCode());
                        BigDecimal unitNV = performance.getUnitNV();
                        //组合首日基金净值
                        FundNetValuePerformance performanceHis = fundDetailService.getFundNetValuePerformanceHis(model.getFundCode(), tradeDay);
                        BigDecimal unitNVhis = performanceHis.getUnitNV();
                        //基金今日收益
                        BigDecimal f1 = baseCalculate.multiply(model.getInvestRate());
                        BigDecimal fundTodayIncome = f1.divide(unitNVhis, 4, BigDecimal.ROUND_HALF_EVEN);
                        fundTodayIncome = fundTodayIncome.multiply(unitNV);

                        FundVo fundVo = new FundVo();
                        fundVo.setFundCode(model.getFundCode());
                        fundVo.setFundAssets(fundTodayIncome);
//                        fundVo.setBeginDate(beginDate);
                        fundVos.add(fundVo);

                        fundTodayIncome = fundTodayIncome.subtract(f1);
                        accumulatedIncome = accumulatedIncome.add(fundTodayIncome);
                    }

                }
            }

            BigDecimal sumPortfoios = new BigDecimal(0);

            for (FundVo fundVo : fundVos) {
                sumPortfoios = sumPortfoios.add(fundVo.getFundAssets());
            }

            for (FundVo fundVo : fundVos) {
                BigDecimal percent = fundVo.getFundAssets().multiply(new BigDecimal(100)).divide(sumPortfoios, 4, BigDecimal.ROUND_HALF_EVEN);
                String percentS = MoneyUtils.formatMoney(percent, 2);
                FundCombinationMapping mapping = fundCombinationMappingService.queryByCombinationCodeAndFundCode(vo.getCombinationCode(), fundVo.getFundCode().trim());

                if (mapping == null) {
                    continue;
                }

                mapping.setFundPercent(percentS);
                fundCombinationMappingService.update(mapping);
            }

            //组合累计收益率
            String accumulatedIncomeS = MoneyUtils.formatMoney(accumulatedIncome.divide(baseCalculate, 4, BigDecimal.ROUND_HALF_EVEN).multiply(new BigDecimal(100)), 2);
            vo.setAccumulatedIncome(accumulatedIncomeS);

            //设置货币基金累计收益
            accCurrencyIncome.setScale(4, BigDecimal.ROUND_UP);
            vo.setAccumCurrencyIncome(accCurrencyIncome.floatValue());

            //设置运行天数

            beginDate = vo.getBeginDate();

            if (beginDate == null) {
                continue;
            }

            Date now = new Date();
            long runday = (now.getTime() - beginDate.getTime()) / (1000*3600*24);
            int rundayS = new Long(runday).intValue();

            vo.setRunDay(rundayS);

            if (runday == 0) {
                continue;
            }

            //设置年化收益
            BigDecimal annualizedIncome = accumulatedIncome.multiply(new BigDecimal(365)).multiply(new BigDecimal(100)).divide(baseCalculate, 4, BigDecimal.ROUND_HALF_EVEN).divide(new BigDecimal(runday), 4, BigDecimal.ROUND_HALF_EVEN);
            annualizedIncome.setScale(2, BigDecimal.ROUND_UP);
            vo.setAnnualizedIncome(annualizedIncome.floatValue());
        }
        return fundCombinationVos;
    }



    @Transactional(readOnly = false)
    public List<FundCombinationVo> getDailyGrowthRates2(Date currentDate) throws BaseAppException{
        Map<String, Object> map = hsPortfolioQryService.query(new PortfolioQryDto());

        BaseResult                result = new BaseResult();
        List<Map<String, Object>> list   = new ArrayList<>();
        HundsunUtils.ConvertToList(map, list, result);

        if (!result.getSuccess()) {
            log.error("获取基金组合失败");
            ExceptionHandler.publish(ErrorConst.COMMON_SYSTEM_ERROR);
        }

        List<PortfolioQryModel> portfolioQryModels = ModelPopulateUtils.populatePortfolioQry(list);

        /**
         * test code
         */
        Iterator<PortfolioQryModel> modelss = portfolioQryModels.iterator();
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        while (modelss.hasNext()) {
            PortfolioQryModel a = modelss.next();

            try {
                if ("2001".equals(a.getPortfolioCode())) {
                    a.setBeginDate(dateFormat.parse("2017-8-18"));
                }

                if ("2002".equals(a.getPortfolioCode())) {
                    a.setBeginDate(dateFormat.parse("2017-9-15"));
                }

                if ("2004".equals(a.getPortfolioCode())) {
                    a.setBeginDate(dateFormat.parse("2017-8-7"));
                }
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }



        Set<String> portfolios = new HashSet<>();

        for (PortfolioQryModel model : portfolioQryModels) {
            if ("1".equals(model.getCombState())) {
                portfolios.add(model.getPortfolioCode());
            }
        }

        List<String> portfolioCodes = new ArrayList<>(portfolios);
        List<FundCombinationVo> fundCombinationVos = new ArrayList<>();

        for (String code : portfolioCodes) {
            FundCombinationVo vo = new FundCombinationVo();
            vo.setCombinationCode(code);

            BigDecimal sumDailyGrowthRate = new BigDecimal(0);

            for (PortfolioQryModel model : portfolioQryModels) {
                if (code.equals(model.getPortfolioCode())) {
                    vo.setCombinationName(model.getProtocolName());

                    try {
                        BigDecimal fundDailyGrowthRate = fundDetailService.getFundDailyGrowthRate(model.getFundCode());

                        if (fundDailyGrowthRate == null) {
                            fundDailyGrowthRate = new BigDecimal(0);
                        }

                        BigDecimal finalDailyGrowthRate = fundDailyGrowthRate.multiply(model.getInvestRate());
                        sumDailyGrowthRate = sumDailyGrowthRate.add(finalDailyGrowthRate);
                    } catch (BaseAppException e) {
                        log.error(e.getMessage(), e);
                    }
                }
            }

            vo.setDailyGrowthRate(MoneyUtils.parseRate(sumDailyGrowthRate));

            fundCombinationVos.add(vo);
        }

        /**
         * 计算组合累计收益
         */
        for (FundCombinationVo vo : fundCombinationVos) {
            BigDecimal accumulatedIncome = new BigDecimal(0);
            FundCombination combination = queryOne(vo.getCombinationCode());

            if (combination == null) {
                continue;
            }

            //货币基金累计收益
            float accumCurrencyIncome = combination.getAccumCurrencyIncome();
            BigDecimal accCurrencyIncome = new BigDecimal(accumCurrencyIncome);
            accumulatedIncome = accumulatedIncome.add(accCurrencyIncome);

            BigDecimal baseCalculate = new BigDecimal(combination.getBaseCalculate());
            Date beginDate = null;

            //test---------------
//            String input = "2017-11-1";
//            DateFormat df = new SimpleDateFormat("yyyy-MM-dd");

            List<FundVo> fundVos = new ArrayList<>();

            for (PortfolioQryModel model : portfolioQryModels) {

                beginDate = model.getBeginDate();
//                try {
//                    beginDate = df.parse(input);
//                } catch (ParseException e) {
//                    e.printStackTrace();
//                }
                if (beginDate == null) {
                    continue;
                }

//                vo.setBeginDate(beginDate);

                Date tradeDay = workingDateService.getLastWorkingDay(beginDate).getLastWorkingDay();



                if (tradeDay == null) {
                    continue;
                }

                Date todayTradeDay = workingDateService.getLastWorkingDay(currentDate).getLastWorkingDay();

                if (vo.getCombinationCode().equals(model.getPortfolioCode())) {

                    //判断历史表是否有重复组合交易日数据，若有，则不再计算

                    List<FundCombinationHistory> histories = fundCombinationHistoryService.queryByTradeDay(vo.getCombinationCode(), todayTradeDay);

                    if (histories != null && histories.size() != 0) {
                        continue;
                    }

                    vo.setBeginDate(beginDate);
                    vo.setTradeDate(todayTradeDay);

                    //轮询基金
                    FundDetail fundDetail = fundDetailService.getFundDetail(model.getFundCode().trim());

                    if (fundDetail == null) {
                        continue;
                    }

                    boolean isCurrency = FundUtil.isCurrency(fundDetail.getFundTypeCode());

                    if (isCurrency) {
                        //货基
                        BigDecimal dailyProfit = fundDetailService.getCurrencyDailyProfit(model.getFundCode());
                        BigDecimal todayIncome = baseCalculate.multiply(model.getInvestRate()).multiply(dailyProfit).divide(new BigDecimal(10000));
                        accumulatedIncome = accumulatedIncome.add(todayIncome);
                        accCurrencyIncome = accCurrencyIncome.add(todayIncome);

                        //计算该货基资产
                        FundCombinationMapping mapping = fundCombinationMappingService.queryByCombinationCodeAndFundCode(vo.getCombinationCode(), model.getFundCode().trim());

                        if (mapping == null) {
                            continue;
                        }

                        Float fundCurrencyAccumIncome = mapping.getFundCurrencyAccumIncome();

                        BigDecimal fundCurrencyAccumIncomeB = null;

                        if (fundCurrencyAccumIncome == null) {
                            fundCurrencyAccumIncomeB = new BigDecimal(0);
                        } else {
                            fundCurrencyAccumIncomeB = new BigDecimal(fundCurrencyAccumIncome);
                        }
                        //货币资产
                        BigDecimal fundAssets = fundCurrencyAccumIncomeB.add(todayIncome).add(baseCalculate.multiply(model.getInvestRate()));
                        mapping.setFundCurrencyAccumIncome(fundCurrencyAccumIncomeB.add(todayIncome).floatValue());

                        //更新mapping中货基累计值
                        fundCombinationMappingService.update(mapping);

                        FundVo fundVo = new FundVo();
                        fundVo.setFundCode(model.getFundCode().trim());
                        fundVo.setFundAssets(fundAssets);
//                        fundVo.setBeginDate(beginDate);
                        fundVos.add(fundVo);
                    } else {
                        //非货基

                        //当前净值
                        FundNetValuePerformance performance = fundDetailService.getFundNetValuePerformanceHis(model.getFundCode(), todayTradeDay);
                        BigDecimal unitNV = performance.getUnitNV();
                        //组合首日基金净值
                        FundNetValuePerformance performanceHis = fundDetailService.getFundNetValuePerformanceHis(model.getFundCode(), tradeDay);
                        BigDecimal unitNVhis = performanceHis.getUnitNV();
                        //基金今日收益
                        BigDecimal f1 = baseCalculate.multiply(model.getInvestRate());
                        BigDecimal fundTodayIncome = f1.divide(unitNVhis, 4, BigDecimal.ROUND_HALF_EVEN);
                        fundTodayIncome = fundTodayIncome.multiply(unitNV);

                        FundVo fundVo = new FundVo();
                        fundVo.setFundCode(model.getFundCode());
                        fundVo.setFundAssets(fundTodayIncome);
//                        fundVo.setBeginDate(beginDate);
                        fundVos.add(fundVo);

                        fundTodayIncome = fundTodayIncome.subtract(f1);
                        accumulatedIncome = accumulatedIncome.add(fundTodayIncome);
                    }

                }
            }

            BigDecimal sumPortfoios = new BigDecimal(0);

            for (FundVo fundVo : fundVos) {
                sumPortfoios = sumPortfoios.add(fundVo.getFundAssets());
            }

            for (FundVo fundVo : fundVos) {
                BigDecimal percent = fundVo.getFundAssets().multiply(new BigDecimal(100)).divide(sumPortfoios, 4, BigDecimal.ROUND_HALF_EVEN);
                String percentS = MoneyUtils.formatMoney(percent, 2);
                FundCombinationMapping mapping = fundCombinationMappingService.queryByCombinationCodeAndFundCode(vo.getCombinationCode(), fundVo.getFundCode().trim());

                if (mapping == null) {
                    continue;
                }

                mapping.setFundPercent(percentS);
                fundCombinationMappingService.update(mapping);
            }

            //组合累计收益率
            String accumulatedIncomeS = MoneyUtils.formatMoney(accumulatedIncome.divide(baseCalculate, 4, BigDecimal.ROUND_HALF_EVEN).multiply(new BigDecimal(100)), 2);
            vo.setAccumulatedIncome(accumulatedIncomeS);

            //设置货币基金累计收益
            accCurrencyIncome.setScale(4, BigDecimal.ROUND_UP);
            vo.setAccumCurrencyIncome(accCurrencyIncome.floatValue());

            //设置运行天数

            beginDate = vo.getBeginDate();

            if (beginDate == null) {
                continue;
            }

            Date now = currentDate;
            long runday = (now.getTime() - beginDate.getTime()) / (1000*3600*24);
            int rundayS = new Long(runday).intValue();

            vo.setRunDay(rundayS);

            if (runday == 0) {
                continue;
            }

            //设置年化收益
            BigDecimal annualizedIncome = accumulatedIncome.multiply(new BigDecimal(365)).multiply(new BigDecimal(100)).divide(baseCalculate, 4, BigDecimal.ROUND_HALF_EVEN).divide(new BigDecimal(runday), 4, BigDecimal.ROUND_HALF_EVEN);
            annualizedIncome.setScale(2, BigDecimal.ROUND_UP);
            log.info("runday===" + rundayS + "   " + "annualizedIncome===" + annualizedIncome);
            vo.setAnnualizedIncome(annualizedIncome.floatValue());
        }
        return fundCombinationVos;
    }

    @Override
    public List<PortfolioQryModel> queryPorfolio(String portfolioCode) {
//        PortfolioQryDto dto = PortfolioQryDto.builder().request_num(GlobalConstant.MAX_REQUEST_NUM).sort_direction("1").qry_beginrownum("1").build();
//
//        Map<String, Object> map = hsPortfolioQryService.query(dto);
//
//        BaseResult                result = new BaseResult();
//        List<Map<String, Object>> list   = new ArrayList<>();
//        HundsunUtils.ConvertToList(map, list, result);
//
//        if (!result.getSuccess()) {
//            log.error("获取基金组合失败");
//            ExceptionHandler.publish(ErrorConst.COMMON_SYSTEM_ERROR);
//        }
//        List<PortfolioQryModel> portfolioQryModels = ModelPopulateUtils.populatePortfolioQry(list);

        //为了调用方法 传个空的
        User user = new User();
        user.setExternalClientId("");
        List<PortfolioQryModel> portfolioQryModels = queryService.getPortfolioQryModel(user);
        Iterator<PortfolioQryModel> modelss = portfolioQryModels.iterator();

        while (modelss.hasNext()) {
            PortfolioQryModel model = modelss.next();

            if (model.getEndDate().before(new Date())) {
                modelss.remove();
            }
        }

        List<PortfolioQryModel> ret = new ArrayList<>();

        for (PortfolioQryModel model : portfolioQryModels) {
            if (EqualsUtil.equals(model.getPortfolioCode(), portfolioCode)) {
                ret.add(model);
            }
        }

        return ret;
    }

    @Override
    public com.codi.base.domain.BaseResult queryPorfolio(Pageable pageable) {
        return com.codi.base.domain.BaseResult.success(fundCombinationDao.query(pageable));
    }

    @Override
    @Transactional(readOnly = false)
    public int addPorfolio(FundCombination combination) {
        combination.setLastUpdatedDate(new Date());
        combination.setState(1);
        combination.setAccumCurrencyIncome(0F);
        return fundCombinationDao.addPortfolio(combination);
    }

    @Override
    @Transactional(readOnly = false)
    public int updatePorfolio(FundCombination combination) {
        combination.setLastUpdatedDate(new Date());
        return fundCombinationDao.updatePortfolio(combination);
    }
}
